#include "FixedCryptoer.h"
#include "Poco/StringTokenizer.h"
#include "Poco\Util\Application.h"
#include "Poco\Util\LayeredConfiguration.h"
#include <sstream>
#include <iostream>
#include <Poco\Logger.h>
using Poco::StringTokenizer;
using Poco::Util::Application;


FixedCryptoer::FixedCryptoer() 
{
}


FixedCryptoer::~FixedCryptoer()
{
}

std::string FixedCryptoer::encodeContents(std::string contents, std::string file_base, std::string file_ext)
{
	Application& app = Application::instance();
	std::string fh = processGlobalMacro(app.config().getString(file_ext + ".line_fix_mode.file_header", ""), file_base,file_ext);
	if (!fh.empty())
		fh += "\r\n";
	std::string ft = processGlobalMacro(app.config().getString(file_ext + ".line_fix_mode.file_tailer", ""), file_base, file_ext);
	std::string lh = processGlobalMacro(app.config().getString(file_ext + ".line_fix_mode.line_header", ""), file_base, file_ext);
	std::string lt = processGlobalMacro(app.config().getString(file_ext + ".line_fix_mode.line_tailer", ""), file_base, file_ext);

	int fixed_length = app.config().getInt("fixed_length", 64);
	std::string out = fh;
	size_t realLen;
	std::string tmp;
	for (int i = 0; i < contents.length(); i += fixed_length) {
		if (i + fixed_length < contents.length()){
			realLen = fixed_length;
		} 
		else{
			realLen = contents.length() - i;

		}
		tmp = contents.substr(i, realLen);
		std::stringstream ss;
		ss << i/fixed_length;
		std::string plh = replaceAll(lh, "%LINE_NUMBER%", ss.str());
		std::string plt = replaceAll(lt, "%LINE_NUMBER%", ss.str());
		out += plh + pCipher->encryptString(tmp, Cipher::ENC_BASE64_NO_LF) + plt +"\r\n";
	}
	out += ft;
	return out;
}

std::string FixedCryptoer::decodeContents(std::string contents, std::string file_base, std::string file_ext)
{
	Application& app = Application::instance();
	std::string fh = processGlobalMacro(app.config().getString(file_ext + ".line_fix_mode.file_header", ""), file_base, file_ext);
	if (!fh.empty())
		fh += "\r\n";
	std::string ft = processGlobalMacro(app.config().getString(file_ext + ".line_fix_mode.file_tailer", ""), file_base, file_ext);
	std::string lh = processGlobalMacro(app.config().getString(file_ext + ".line_fix_mode.line_header", ""), file_base, file_ext);
	std::string lt = processGlobalMacro(app.config().getString(file_ext + ".line_fix_mode.line_tailer", ""), file_base, file_ext);
	std::string out;
	size_t fhlen = fh.length();
	size_t ftlen = ft.length();

	std::string sbuf = contents.substr(fhlen, contents.length() - fhlen - ftlen);
	StringTokenizer st(sbuf, "\n", StringTokenizer::TOK_TRIM | StringTokenizer::TOK_IGNORE_EMPTY);
	StringTokenizer::Iterator it = st.begin();
	int i = 0;
	while (it != st.end()) {
		std::stringstream ss;
		ss << i++;
		std::string plh = replaceAll(lh, "%LINE_NUMBER%", ss.str());
		std::string plt = replaceAll(lt, "%LINE_NUMBER%", ss.str());
		size_t lhlen = plh.length();
		size_t ltlen = plt.length();
		std::string cur = *it++;
		std::string curbuf = cur.substr(lhlen, cur.length() - lhlen - ltlen);
		out+= pCipher->decryptString(curbuf, Cipher::ENC_BASE64_NO_LF);
	}
	return out;
}

void FixedCryptoer::showInfo()
{
	Application& app = Application::instance();
	app.logger().information("Using fixed mode.\n");
}
